package controllers

import (
	"fly/global"
	"fly/helper"
	"fly/models"
	"fly/req"
	"fly/resp"
	"fly/schema"
	"fly/service"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/duke-git/lancet/v2/condition"
	"github.com/duke-git/lancet/v2/convertor"
	"github.com/duke-git/lancet/v2/slice"
	"net/url"
)

// AircraftController 飞机
type AircraftController struct {
	BaseController
	AircraftService           service.AircraftService
	SysUserService            service.SysUserService
	SysDictService            service.SysDictService
	SysDeptService            service.SysDeptService
	FlightTaskService         service.FlightTaskService
	AircraftExperienceService service.AircraftExperienceService
	AircraftComponentService  service.AircraftComponentService
}

// Save ...
// @Title 添加或者编辑飞机
// @Description 添加或者编辑飞机
// @Param token header  string	false "授权Token"
// @Param body body req.AircraftSaveReq true "添加或者编辑飞机"
// @Success 200 {object} resp.AircraftResp
// @router /save [post]
func (c *AircraftController) Save() {
	con := req.AircraftSaveReq{}
	c.CheckReqErrorAbort(c.BindJSON(&con))
	c.ValidReqParams(&con)
	mAircraft := models.Aircraft{}
	c.CheckRespErrorAbort(helper.CopyDeep(&mAircraft, con))
	mAircraft.FactoryTime = helper.Int2Time(con.FactoryTime)
	var err error
	stateDict, err := c.SysDictService.GetSimpleDictById(con.StateDictId)
	c.CheckReqErrorAbort(err)
	c.CheckReqErrorAbort(helper.RequireTrue(stateDict != nil, "状态字典值不存在"))

	isNormal := stateDict.DicCode == schema.AircraftStateKey && stateDict.DicKey == schema.AircraftNormalKey
	id := con.Id
	uid := c.GetReqUserId()
	if con.Id > 0 {
		old, _ := models.GetAircraftById(id)
		c.CheckReqErrorAbort(helper.RequireTrue(old != nil, "未找到资源"))
		locationEnable, _ := c.AircraftService.EnableLocationPutAircraft(con.LocationId)
		if old.LocationId != con.LocationId && !locationEnable {
			c.CheckReqErrorAbort(fmt.Errorf("当前机位已被占用"))
		}
		if old.Code != con.Code {
			cacheAir, _ := c.AircraftService.GetSimpleAircraftByCode(con.Code)
			c.CheckReqErrorAbort(helper.RequireTrue(cacheAir == nil, "已存在此飞机编号"))
		}
		err = helper.CopyOut(old, con)
		c.CheckReqErrorAbort(err)
		if !isNormal && old.Status >= 0 {
			old.Status = schema.Disable
		} else {
			old.Status = schema.Enabled
		}
		err = models.UpdateAircraftById(old, uid)
	} else {
		locationEnable, _ := c.AircraftService.EnableLocationPutAircraft(con.LocationId)
		c.CheckReqErrorAbort(helper.RequireTrue(locationEnable, "当前机位已被占用"))
		cacheAir, _ := c.AircraftService.GetSimpleAircraftByCode(mAircraft.Code)
		c.CheckReqErrorAbort(helper.RequireTrue(cacheAir == nil, "已存在此飞机编号"))
		if isNormal {
			mAircraft.Status = schema.Enabled
		} else {
			mAircraft.Status = schema.Disable
		}
		id, err = models.AddAircraft(&mAircraft, uid)
	}
	c.CheckRespErrorAbort(err)
	// 保存经历
	err = c.AircraftExperienceService.SaveOrUpdate(id, con.Experiences, uid)
	_ = global.DelCache(fmt.Sprintf(service.AircraftCacheSimple, id))
	c.CheckRespErrorAbort(err)
	// 保存组件
	_ = c.AircraftComponentService.SaveOrUpdateComponent(id, con.DeptId, con.TotalUpDown, con.ComponentSaveReq, uid, uid)
	r := resp.AircraftResp{}
	airport, err := models.GetAircraftById(id)
	c.CheckRespErrorAbort(err)
	err = resp.Copy2TimeResp(&r, airport)
	c.CheckRespErrorAbort(err)
	r.CreatorName, err = c.SysUserService.GetUserRealNameById(uid)
	r.UpdaterName = r.CreatorName
	c.CheckRespErrorAbort(err)
	c.Success(r)
}

// Del ...
// @Title 删除飞机
// @Description 删除飞机
// @Param token header  string	false "授权Token"
// @Param path id int true "飞机id"
// @Success 200 {int} "id"
// @router /:id [delete]
func (c *AircraftController) Del() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	c.CheckReqErrorAbort(helper.RequireTrue(c.SysUserService.IsSuperAdminUser(c.GetReqUserId()), "超级管理员才能操作"))
	taskCount, _ := orm.NewOrm().QueryTable(new(models.FlightTask)).Filter("aircraft_id", id).Count()
	c.CheckReqErrorAbort(helper.RequireTrue(taskCount == 0, "该飞机还有任务关联使用"))
	// 删除飞机下的经历关系
	_, err = orm.NewOrm().QueryTable(new(models.AircraftExperience)).Filter("aircraft_id", id).Delete()
	_ = global.DelCache(fmt.Sprintf(service.AircraftCacheSimple, id))
	// 删除飞机下的配件关系
	_, err = orm.NewOrm().QueryTable(new(models.AircraftComponentRel)).Filter("aircraft_id", id).Delete()
	c.CheckRespErrorAbort(models.DeleteAircraft(id))
	c.Success(id)
}

// Enable 停用启用
// @Title Enable
// @Description 停用启用
// @Param token header  string	false "授权Token"
// @Param path id int true "字典id"
// @Success 200 {int} "id"
// @router /enable/:id [put]
func (c *AircraftController) Enable() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	m, err := models.GetAircraftById(id)
	c.CheckAssertAbort(m, "资源不存在")
	m.Enabled = condition.TernaryOperator(m.Enabled == schema.Disable, schema.Enabled, schema.Disable)
	c.CheckRespErrorAbort(models.UpdateAircraftById(m, c.GetReqUserId()))
	_ = global.DelCache(fmt.Sprintf(service.AircraftCacheSimple, id))
	c.Ok()
}

// Index ...
// @Title 飞机列表
// @Description 飞机列表
// @Param token header  string	false "授权Token"
// @Param keywords query  string false "搜索字段"
// @Param pageNum query  int false "当前页"
// @Param pageSize query  int false "每页数量"
// @Param total query  int false "数据总数"
// @Param code query  string false "飞机编号"
// @Param status query  int false "飞机状态"
// @Param deptId query  int false "部门"
// @Param experienceId query  int false "经历Id"
// @Param startTime query  int false "录入开始时间"
// @Param endTime query  int false "录入结束时间"
// @Param typeDictId query  int false "飞机类型"
// @Param stateDictId query  int false "飞机状态Id"
// @Success 200 {object} []service.Pagination
// @router / [get]
func (c *AircraftController) Index() {
	subIds, err := c.SysDeptService.GetSubDeptIdListByUserId(c.GetReqUserId())
	c.CheckRespErrorAbort(err)
	params, _ := url.ParseQuery(c.Ctx.Request.URL.RawQuery)
	data, pagination := c.AircraftService.GetPaginateData(params, subIds)
	var airportList []resp.AircraftResp
	c.CheckRespErrorAbort(resp.Copy2TimeResp(&airportList, &data))
	for i, airport := range data {
		airportList[i].CreatorName, _ = c.SysUserService.GetUserRealNameById(airport.Creator)
		airportList[i].UpdaterName, _ = c.SysUserService.GetUserRealNameById(airport.Updater)
		airportList[i].AircraftName, _ = c.SysDictService.GetDictValueById(airport.TypeDictId)
		airportList[i].StateName, _ = c.SysDictService.GetDictValueById(airport.StateDictId)
		airportList[i].DeptName, _ = c.SysDeptService.GetSimpleDeptNameById(airport.DeptId)
		airportList[i].LifetimeRemindStatus, _ = c.AircraftComponentService.GetAircraftLifetimeStatus(airport.Id)
		airportList[i].Experiences, _ = c.AircraftExperienceService.GetSimpleExperienceList(airport.Id)
		tasks, err := c.FlightTaskService.GetWaitTasksByAircraftId(airport.Id)
		if err == nil && len(tasks) > 0 {
			taskList := slice.Map(tasks, func(index int, item *models.FlightTask) *resp.FlightTaskSimpleResp {
				taskResp := resp.FlightTaskSimpleResp{}
				_ = resp.Copy2TimeResp(&taskResp, item)
				return &taskResp
			})
			airportList[i].FlightTasks = taskList
		}
	}
	pagination.List = airportList
	c.Success(pagination)
}

// List ...
// @Title 所有可用飞机列表
// @Description 所有飞机列表-用于首页显示
// @Param token header  string	false "授权Token"
// @Param type query  int false "飞机类型"
// @Success 200 {object} []resp.AircraftResp
// @router /list [get]
func (c *AircraftController) List() {
	subIds, err := c.SysDeptService.GetSubDeptIdListByUserId(c.GetReqUserId())
	c.CheckRespErrorAbort(err)
	list, err := c.AircraftService.GetAllAircraft(subIds)
	c.CheckRespErrorAbort(err)
	var aircraftList []resp.AircraftResp
	c.CheckRespErrorAbort(resp.Copy2TimeResp(&aircraftList, &list))
	for i, airport := range list {
		aircraftList[i].AircraftName, _ = c.SysDictService.GetDictValueById(airport.TypeDictId)
		aircraftList[i].StateName, _ = c.SysDictService.GetDictValueById(airport.StateDictId)
		aircraftList[i].DeptName, _ = c.SysDeptService.GetSimpleDeptNameById(airport.DeptId)
		aircraftList[i].IsFlightPool, _ = c.AircraftService.IsFlightPool(airport)
		tasks, err := c.FlightTaskService.GetWaitTasksByAircraftId(airport.Id)
		if err == nil && len(tasks) > 0 {
			taskList := slice.Map(tasks, func(index int, item *models.FlightTask) *resp.FlightTaskSimpleResp {
				taskResp := resp.FlightTaskSimpleResp{}
				_ = resp.Copy2TimeResp(&taskResp, item)
				return &taskResp
			})
			aircraftList[i].FlightTasks = taskList
		}
	}
	c.Success(aircraftList)
}

// Detail ...
// @Title 飞机详情
// @Description 通过id查询飞机详情
// @Param token header  string	false "授权Token"
// @Param path id int true "角色id"
// @Success 200 {object} []resp.AircraftResp
// @router /:id [get]
func (c *AircraftController) Detail() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	aircraft, err := models.GetAircraftById(id)
	c.CheckRespErrorAbort(err)
	respAircraft := resp.AircraftResp{}
	_ = resp.Copy2TimeResp(&respAircraft, aircraft)
	respAircraft.CreatorName, _ = c.SysUserService.GetUserRealNameById(aircraft.Creator)
	respAircraft.UpdaterName, _ = c.SysUserService.GetUserRealNameById(aircraft.Updater)
	respAircraft.AircraftName, _ = c.SysDictService.GetDictValueById(aircraft.TypeDictId)
	respAircraft.StateName, _ = c.SysDictService.GetDictValueById(aircraft.StateDictId)
	respAircraft.DeptName, _ = c.SysDeptService.GetSimpleDeptNameById(aircraft.DeptId)
	respAircraft.LifetimeRemindStatus, _ = c.AircraftComponentService.GetAircraftLifetimeStatus(id)
	respAircraft.Experiences, _ = c.AircraftExperienceService.GetSimpleExperienceList(id)
	tasks, err := c.FlightTaskService.GetWaitTasksByAircraftId(id)
	if err == nil && len(tasks) > 0 {
		taskList := slice.Map(tasks, func(index int, item *models.FlightTask) *resp.FlightTaskSimpleResp {
			taskResp := resp.FlightTaskSimpleResp{}
			_ = resp.Copy2TimeResp(&taskResp, item)
			return &taskResp
		})
		respAircraft.FlightTasks = taskList
	}
	list, err := c.AircraftComponentService.GetAircraftComponents(id)
	if err == nil && len(list) > 0 {
		var componentList []*resp.AircraftComponentResp
		c.CheckRespErrorAbort(resp.Copy2TimeResp(&componentList, &list))
		for i, airport := range list {
			componentList[i].DeptName, _ = c.SysDeptService.GetSimpleDeptNameById(airport.DeptId)
		}
		respAircraft.BindComponents = componentList
	}

	var rels []*models.AircraftComponentRel
	_, err = orm.NewOrm().QueryTable(new(models.AircraftComponentRel)).Filter("aircraft_id", id).All(&rels)
	if err == nil && len(rels) > 0 {
		respAircraft.Components = slice.Map(rels, func(index int, item *models.AircraftComponentRel) *resp.AircraftComponentResp {
			componentResp := resp.AircraftComponentResp{}
			component, e := models.GetAircraftComponentById(item.ComponentId)
			if e != nil {
				return nil
			}
			_ = resp.Copy2TimeResp(&componentResp, component)
			componentResp.DeptName, _ = c.SysDictService.GetDictValueById(component.DeptId)
			componentResp.StateName, _ = c.SysDictService.GetDictValueById(component.StateDictId)
			return &componentResp
		})
	}
	c.Success(respAircraft)
}
